#pragma once
#include "DAEMatrix.h"
#include "StoredAnimationNode.h"
#include "TRSTransform.h"
#include <vector>

class Skeleton;
/**
* Class that represents a node in a skeleton.
* The Bone class is a subclass of this class.
* @author Koen Samyn
*/
class SkeletonNode
{
	
public:
	typedef vector<SkeletonNode*>::const_iterator SNIT ;
	/**
	* Creates a new control node object
	* @param name the name for the bone.
	* @param id the bone id.
	*/
	SkeletonNode(tstring name, int id=-1);
	/**
	* Destroys the control node object
	*/
	virtual ~SkeletonNode(void);
	/**
	* Get the name of the node
	*/
	tstring GetName(){
		return m_Name;
	}

	/**
	* Returns the id for the bone.
	* @return the bone id.
	*/
	int GetID(){
		return m_ID;
	}

	/**
	* Sets the parent for this skeleton node.
	* @param parent the parent node for this object.
	*/
	void SetParent(SkeletonNode* parent){
		m_Parent = parent;
	}

	/**
	* Returns the parent for this skeleton node.
	* @return the skeleton node parent.
	*/
	SkeletonNode* GetParent(){
		return m_Parent;
	}

	/**
	* Adds a bone as child to this bone.
	* @param child the bone to add as child of this bone.
	*/
	void AddNode(SkeletonNode* child){
		m_ChildNodes.push_back(child);
		child->SetParent(this);
	}

	/**
	* Returns the begin of the vector with child nodes.
	* @return the iterator for the beginning of the vector.
	*/
	SNIT GetChildNodeBegin(){
		return m_ChildNodes.begin();
	}

	/**
	* Returns the end of the vector with child nodes.
	* @return the iterator for the end of the vector.
	*/
	SNIT GetChildNodeEnd(){
		return m_ChildNodes.end();
	}

	/**
	* Sets the initial transform for this bone.
	* @param tx the x translation.
	* @param ty the y translation.
	* @param tz the z translation.
	* @param rx the rotation about the x axis
	* @param ry the rotation about the y axis.
	* @param rz the rotation about the z axis.
	* @param sx the x scale factor (default 1)
	* @param sy the y scale factor (default 1)
	* @param sz the z scale factor (default 1)
	*/
	void SetTransform(float tx, float ty,float tz, float rx, float ry, float rz, float sx=1, float sy=1,float sz=1);
	/**
	* Sets the rotation of this node.
	* @param rx the rotation about the x axis
	* @param ry the rotation about the y axis.
	* @param rz the rotation about the z axis.
	*/
	void SetRotation(float rx, float ry, float rz);
	/**
	* Returns the global transformation for this node.
	* @return the DAEMatrix global transformation.
	*/ 
	const DAEMatrix& GetGlobalTransformation(){
		return m_GlobalTrans;
	}

	const DAEMatrix& GetInitialPose(){
		return m_InitialPose.GetCompiledMatrix();
	}

	/**
	* Set the animation for this node.
	* @param an the animation for the node.
	*/
	void SetAnimationNode(AnimationNode * an){
		m_pAnimation = an;
		if ( an != NULL )
			an->SetSkeletonNode(this);
	}

	/**
	* Animates this node, according to the 
	* provided time.
	* @param skeleton the skeleton this animation is a child of.
	* @param an extra transformation to apply to the child transformation.
	* @param time the animation time (must be between start & stop interval)
	*/
	void Animate(Skeleton* skeleton, DAEMatrix& deltaTrans, float time);

	/**
	* Creates a clone of this SkeletonNode object.
	* @return a clone of the SkeletonNode object.
	*/
	virtual SkeletonNode* Clone() const;
	/**
	* Get the rotation of the initial pose of the skeletonnode.
	* @param rotation the inout parameter for the rotation.
	*/
	void GetRotation(DAEFloat3& rotation);
	/**
	* Get the translation of the initial pose of the skeletonnode.
	* @param translation the inout parameter for the translation.
	*/
	void GetTranslation(DAEFloat3& translation);
	/**
	* Get the scale of the initial pose of the skeletonnode.
	* @param scale the inout parameter for the scale.
	*/
	void GetScale(DAEFloat3& scale);
protected:
	/**
	* The child nodes of this node
	*/
	vector<SkeletonNode*> m_ChildNodes;
	/**
	* The animation node for this node object.
	* This contains the animation data for this node.
	*/
	AnimationNode* m_pAnimation;
	/**
	* The resulting transformation for this node.
	*/
	DAEMatrix m_GlobalTrans;
	/**
	* the id for the bone.
	*/
	int m_ID;
	/**
	* The inverse bone matrix.
	*/
	DAEMatrix m_BoneInv;
	/**
	* The initial pose for this bone.
	*/
	TRSTransform m_InitialPose;
private:
	/**
	* The name of this node.
	*/
	tstring m_Name;
	/**
	* The parent of this node object. Set to NULL if
	* this is a root node.
	*/
	SkeletonNode* m_Parent;
	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	SkeletonNode(const SkeletonNode& t);
	SkeletonNode& operator=(const SkeletonNode& t);
	
};
